package router;

/**
 * Diese Klasse repräsentiert die Interface Datenstruktur, wie sie im OSPF Protokoll vorgesehen ist. 
 */
	import java.awt.List;
import java.net.InetAddress;
import java.net.InterfaceAddress;
	import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
	import java.util.Timer;
	import java.util.TimerTask;

import org.jnetpcap.PcapIf;

import dataStructures.NeighborDataStructure;

import statemachine.InterfaceStateMachine;
	import statemachine.StateInterface;

	import events.EventManager;
	import events.SendHelloEvent;
import events.WaitTimerExpiredEvent;


	public class Interface {
		

		private InterfaceStateMachine stateMachine;
		/**
		 * Der ProtocolPacketReceiver, der die Pakete für dieses Interface empfängt.
		 */
		private ProtocolPacketReceiver receiver;
		/**
		 * Der ProtocolPacketSender, der Pakete für deses Interface sendet.
		 */
		private ProtocolPacketSender sender;
		
		public enum NetworkTypes{
			broadcast, pointToPoint, nbma, pointToMultiPoint, virtualLink;
		}
		
		private InetAddress ipAddress; 
		private short networkMask;
		private StateInterface state;
		private int areaID;
		private NetworkTypes networkType;
		private int cost;
		private int routerDeadIntervall; 
		private Timer helloTimer; 
		private Timer waitTimer;
		private int helloInterval;
		private NetworkInterface networkInterface;
		
		/**
		 * Innere Klasse: Repräsentiert die Aufgabe, die ausgeführt wird sobald der WaitTimer ausläuft.
		 * @author pascal
		 *
		 */
		private class HelloTimerTask extends TimerTask{

			private Interface interf;
			
			public HelloTimerTask(Interface interf){
				this.interf = interf;
			}
			
			@Override
			public void run() {
				EventManager.getInstance().notifyTimerExpired(new SendHelloEvent(interf));
				
			}
			
		}
		
		/**
		 * Innere Klasse: Repräsentiert die Aufgabe, die ausgeführt wird sobald der WaitTimer ausläuft.
		 * @author pascal
		 *
		 */
		private class WaitTimerTask extends HelloTimerTask{
			public WaitTimerTask(Interface interf) {
				super(interf);
			}
			
			@Override
			public void run(){
				EventManager.getInstance().notifyTimerExpired(new WaitTimerExpiredEvent(super.interf));
			}
			
		}
		
		public StateInterface getState(){
			return this.state;
		}
		
		/**
		 * Im Konstruktor werden die wichtigsten Parameter für dieses Interface zugewiesen. Weiterhin werden hier die Timer (HelloTimer und WaitTimer) 
		 * wie sie im OSPF-Protokoll vorgesehen sind gestartet.
		 * @param areaID
		 * @param type
		 * @param cost
		 * @param networkInterf
		 * @param ipAddress
		 * @param networkMask
		 */
		public Interface(int areaID, String type, int cost, NetworkInterface networkInterf, InetAddress ipAddress, short networkMask){
			
			this.areaID = areaID;
			this.cost = cost;
			this.networkInterface = networkInterf;
			this.ipAddress = ipAddress;
			this.networkType = NetworkTypes.valueOf(type);
			
			this.waitTimer = new Timer();
			waitTimer.schedule(new WaitTimerTask(this), routerDeadIntervall*1000);
			this.helloTimer = new Timer();
			helloTimer.schedule(new HelloTimerTask(this), helloInterval*1000);
			
			this.receiver = new ProtocolPacketReceiver(this);
			
			stateMachine = InterfaceStateMachine.getInstance();
			
		}
		
		public void run(){
			receiver.run();
		}
		
		@Override
		public boolean equals(Object obj) {
			Interface interf = (Interface)obj;
			if(this.getInterfaceID().equals(interf) && this.getNetworkMask() == interf.getNetworkMask()){
				return true;
			}
			else return false;
		}
		
		public NetworkInterface getNetworkInterface(){
			return this.networkInterface;
		}
		
		public NetworkTypes getNetworkType(){
			return this.networkType;
		}
		
		public InetAddress getInterfaceID(){
			return this.ipAddress;
		}
		
		public void sendHelloPacketToAll(){
			//TODO Method-Stub
		}
		
		public void sendHelloPacket(NeighborDataStructure recipient){
			//TODO Method-Stub
		}
		
		public void sendDatabaseDescriptionPacket(NeighborDataStructure recipient){
			//TODO Method-Stub
		}
		
		public void sendLinkStateRequestPacket(NeighborDataStructure recipient){
			//TODO Method-Stub
		}
		
		public void sendLinkStateUpdatePacket(NeighborDataStructure recipient){
			//TODO Method-Stub
		}
		
		public void sendLinkStateAckPacket(NeighborDataStructure recipient){
			//TODO Method-Stub
		}
		
		public short getNetworkMask(){
			return this.networkMask;
		}
		
		
		
	}



